#include <stdio.h>

// ============= 第二课：指针基本操作 =============
// 深入理解指针运算、指针与数组的关系

int main(void) {
    printf("=== C语言指针学习 - 第二课：指针基本操作 ===\n\n");
    
    // 1. 指针运算基础
    printf("1. 指针运算基础：\n");
    int numbers[5] = {10, 20, 30, 40, 50};
    int *ptr = numbers;  // 指向数组第一个元素
    
    printf("   数组: [10, 20, 30, 40, 50]\n");
    printf("   int *ptr = numbers;  // ptr指向数组第一个元素\n");
    printf("   ptr 指向的值: %d (地址: %p)\n", *ptr, (void*)ptr);
    printf("\n");
    
    // 2. 指针的递增和递减
    printf("2. 指针的递增和递减：\n");
    printf("   ptr++; 后:\n");
    ptr++;
    printf("   ptr 指向的值: %d (地址: %p)\n", *ptr, (void*)ptr);
    
    printf("   ptr += 2; 后:\n");
    ptr += 2;
    printf("   ptr 指向的值: %d (地址: %p)\n", *ptr, (void*)ptr);
    
    printf("   ptr--; 后:\n");
    ptr--;
    printf("   ptr 指向的值: %d (地址: %p)\n", *ptr, (void*)ptr);
    printf("\n");
    
    // 3. 指针算术的重要特性
    printf("3. 指针算术的重要特性：\n");
    ptr = numbers;  // 重置指针到数组开始
    printf("   指针每次递增移动的字节数 = sizeof(数据类型)\n");
    printf("   int类型大小: %lu 字节\n", sizeof(int));
    printf("   ptr 地址: %p\n", (void*)ptr);
    printf("   ptr+1 地址: %p\n", (void*)(ptr+1));
    printf("   地址差: %ld 字节\n", (char*)(ptr+1) - (char*)ptr);
    printf("\n");
    
    // 4. 使用指针遍历数组
    printf("4. 使用指针遍历数组：\n");
    printf("   方法1 - 使用指针递增:\n");
    ptr = numbers;
    for (int i = 0; i < 5; i++) {
        printf("   numbers[%d] = %d (通过 *ptr = %d)\n", i, numbers[i], *ptr);
        ptr++;
    }
    printf("\n");
    
    printf("   方法2 - 使用指针偏移:\n");
    ptr = numbers;
    for (int i = 0; i < 5; i++) {
        printf("   numbers[%d] = %d (通过 *(ptr+%d) = %d)\n", i, numbers[i], i, *(ptr+i));
    }
    printf("\n");
    
    // 5. 指针比较
    printf("5. 指针比较：\n");
    int *start = numbers;
    int *end = numbers + 4;  // 指向最后一个元素
    
    printf("   start 指向: %d (地址: %p)\n", *start, (void*)start);
    printf("   end 指向: %d (地址: %p)\n", *end, (void*)end);
    printf("   start < end: %s\n", (start < end) ? "true" : "false");
    printf("   end - start = %ld (元素间距)\n", end - start);
    printf("\n");
    
    // 6. 指针与数组名的关系
    printf("6. 指针与数组名的关系：\n");
    printf("   数组名本质上是指向第一个元素的常量指针\n");
    printf("   numbers == &numbers[0]: %s\n", (numbers == &numbers[0]) ? "true" : "false");
    printf("   *numbers == numbers[0]: %s\n", (*numbers == numbers[0]) ? "true" : "false");
    printf("   *(numbers + 2) == numbers[2]: %s\n", (*(numbers + 2) == numbers[2]) ? "true" : "false");
    printf("\n");
    
    // 7. 危险操作警告
    printf("7. 危险操作警告：\n");
    printf("   以下操作是危险的，可能导致程序崩溃:\n");
    printf("   - 访问数组边界外的内存\n");
    printf("   - 使用未初始化的指针\n");
    printf("   - 解引用空指针\n");
    printf("   - 释放已释放的内存\n");
    printf("\n");
    
    // 8. 安全的指针操作示例
    printf("8. 安全的指针操作示例：\n");
    ptr = numbers;
    int array_size = 5;
    
    printf("   安全遍历数组:\n");
    for (int i = 0; i < array_size; i++) {
        if (ptr != NULL && ptr >= numbers && ptr < numbers + array_size) {
            printf("   安全访问: *ptr = %d\n", *ptr);
            ptr++;
        }
    }
    printf("\n");
    
    printf("=== 第二课总结 ===\n");
    printf("1. 指针运算会根据数据类型自动调整步长\n");
    printf("2. ptr++ 使指针移动到下一个元素\n");
    printf("3. ptr + n 使指针向前移动n个元素\n");
    printf("4. 指针可以进行比较和相减操作\n");
    printf("5. 数组名等价于指向第一个元素的常量指针\n");
    printf("6. 始终要进行边界检查以避免内存访问错误\n");
    
    return 0;
} 